package com.jalonjia.seckill.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.jalonjia.seckill.common.core.constant.CacheConstants;
import com.jalonjia.seckill.common.core.util.R;
import com.jalonjia.seckill.common.security.util.SecurityUtils;
import com.jalonjia.seckill.core.dto.SeckillActivityDetail;
import com.jalonjia.seckill.core.entity.SeckillActivity;
import com.jalonjia.seckill.core.entity.SeckillOrder;
import com.jalonjia.seckill.core.entity.SeckillTarget;
import com.jalonjia.seckill.core.service.SeckillActivityService;
import com.jalonjia.seckill.core.service.SeckillService;
import com.jalonjia.seckill.core.service.SeckillTargetService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;

@Slf4j
@Service
@RequiredArgsConstructor
public class SeckillServiceImpl implements SeckillService {
	private final SeckillTargetService seckillTargetService;
	private final SeckillActivityService seckillActivityService;
	private final AmqpTemplate amqpTemplate;
	private final RedisTemplate<String, Object> redisTemplate;

	@Override
	public SeckillActivityDetail getActivityDetailByNo(Long activityNo) {
		SeckillActivity seckillActivity = seckillActivityService.getById(activityNo);
		if (seckillActivity == null) {
			throw new RuntimeException("秒杀活动不存在");
		}
		SeckillTarget seckillTarget = seckillTargetService.getById(seckillActivity.getTargetNo());
		return new SeckillActivityDetail(seckillActivity, seckillTarget);
	}

	/**
	 * 提交秒杀订单
	 * 此服务内基于Redis对秒杀订单进行验证，验证通过后发送MQ保存订单，保存时基于Mysql验证订单
	 *
	 * @param seckillOrder 秒杀订单
	 */
	@Override
	public R submitOrder(SeckillOrder seckillOrder) {
		if(seckillActivityService.activityWarmingUp(seckillOrder.getId())){
			log.warn("秒杀活动缓存预热中提单:{}",seckillOrder.getActivityNo());
			return R.failed("秒杀活动预热中，请稍候");
		}
		String username = SecurityUtils.username();
		seckillOrder.setCreateBy(username);
		String submitKey = String.format("%s:%s:%s", CacheConstants.SECKILL_SUBMIT, seckillOrder.getActivityNo(), username);
		String activityKey = CacheConstants.SECKILL_ACTIVITY + seckillOrder.getActivityNo();
		String targetNumKey = CacheConstants.TARGET_NUM + seckillOrder.getTargetNo();

		SeckillActivity seckillActivity = (SeckillActivity) redisTemplate.opsForValue().get(activityKey);
		if (seckillActivity == null) {
			log.warn("秒杀活动缓存为空：{}", activityKey);
			seckillActivity = seckillActivityService.getById(seckillOrder.getActivityNo());
			seckillActivityService.warmupActivity(Arrays.asList(seckillActivity));
		}
		// 验证秒杀活动时间
		if(!seckillActivityService.duringActivity(seckillActivity)){
			log.warn("不在秒杀活动时间内:{}", seckillActivity.getId());
			return R.failed("不在秒杀活动时间内");
		}
		// 验证重复提单
		if (redisTemplate.opsForValue().get(submitKey) != null && !SecurityUtils.isAdmin()) {
			log.info("用户已提交订单");
			return R.failed("用户已提交订单");
		}
		// 验证秒杀对象数量
		try{
			Long remainNum = redisTemplate.opsForValue().decrement(targetNumKey);
			if (remainNum == null || remainNum < 0L) {
//			log.info("已抢光 {} RedisNum = {}", seckillActivity.getTitle(), remainNum);
				return R.failed("已抢光");
			}
		}catch (Exception e){
			log.error(e.getLocalizedMessage());
			return R.failed("已抢光");
		}
		// 保存秒杀订单
		String seckillOrderJson = JSON.toJSONString(seckillOrder);
		log.info("发送MQ saveOrder:{}", seckillOrderJson);
		amqpTemplate.convertAndSend("saveOrder", JSON.toJSONString(seckillOrder));
		// 记录秒杀订单
		redisTemplate.opsForValue().set(submitKey, Boolean.TRUE);
		return R.ok();
	}
}
